﻿using Cms.Core.Application.IService.PermissionInfo;
using Cms.Core.Infrastructure.AuthHelper;
using Cms.Core.Infrastructure.Dependency;
using Cms.Core.Infrastructure.Extension;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Cms.Core.Web.AuthHelper
{
    /// <summary>
    /// 自定义策略类PermissionHandler, 继承AuthorizationHandler ，并且需要一个权限必要参数
    /// 权限授权Handler
    /// </summary>
    public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
    {


        //验证方案提供对象
        public IAuthenticationSchemeProvider Schemes { get; set; }

   


        public PermissionHandler(IAuthenticationSchemeProvider scheme)
        {
            Schemes = scheme;
        }



        /// <summary>
        /// 重载异步处理程序
        /// </summary>
        /// <param name="context"></param>
        /// <param name="requirement">自定义策略参数</param>
        /// <returns></returns>
        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
        {
            //查询数据库。。。。目前为空...
            //requirement.Permissions = new List<PermissionItem>();

            //从AuthorizationHandlerContext转成HttpContext，以便取出表头信息
            var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;

            //请求Url
            var questUrl = httpContext.Request.Path.Value.ToLower();

            //判断请求是否停止
            var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();

            foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
            {
                var handler = await handlers.GetHandlerAsync(httpContext, scheme.Name) as IAuthenticationRequestHandler;
                if (handler != null && await handler.HandleRequestAsync())
                {
                    context.Fail();
                    return;
                }
            }

            //判断请求是否拥有凭据，即有没有登录
            var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
            if (defaultAuthenticate.IsNotNull())
            {
                var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);

                //result?.Principal不为空即登录成功
                if (result?.Principal != null)
                {
                  
                    httpContext.User = result.Principal;
                    var httpContextUser = httpContext.User;
                    var claims = httpContext.User.Claims;
                    Guid userId = claims.FirstOrDefault(o => o.Type == JwtRegisteredClaimNames.Jti).Value.AsTo<Guid>(); //得到用户ID
                    var permissionService = ServiceLocator.Instance.GetService<IPermissionService>();
                    var permissions = (await permissionService.GetUserAuthorizationUrl(userId)).Select(o => new PermissionItem { Role = o.RoleName, Url = o.Url }); //得到当前用户所有角色的权限
                    requirement.Permissions = permissions.ToList(); 

                    //权限中是否存在请求的url
                    if (permissions.GroupBy(g => g.Url).Where(o => o.Key?.ToLower() == questUrl).Any())
                    {

                        // 获取当前用户的角色信息

                        var currentUserRoles = claims.Where(o => o.Type == requirement.ClaimType).Select(o => o.Value).ToArray();
                        //验证权限
                        //if (Requirement.Permissions.Where(w => w.Name == name && w.Url.ToLower() == questUrl).Count() <= 0)
                        //{
                        //    //无权限跳转到拒绝页面
                        //    httpContext.Response.Redirect(requirement.DeniedAction);
                        //}

                        //判断角色下对应的url是否正确
                        var isRoleAndUrlExist = permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl);
                        //验证权限
                        if (!currentUserRoles.Any() || !isRoleAndUrlExist.Any())
                        {

                            context.Fail();
                            return;
                            // 可以在这里设置跳转页面，不过还是会访问当前接口地址的
                            //httpContext.Response.Redirect(requirement.DeniedAction);
                        }
                    }
                    else
                    {
                        context.Fail();
                        return;
                    }

                    var expirationValue = claims.FirstOrDefault(o => o.Type == ClaimTypes.Expiration)?.Value;
                    //判断过期时间
                    if (expirationValue.IsNotNull() && expirationValue.AsTo<DateTime>() >= DateTime.Now)
                    {
                        context.Succeed(requirement);
                    }
                    else
                    {
                        context.Fail();
                        return;
                    }
                    return;
                }
            }

            //判断没有登录时，是否访问登录的url,并且是Post请求，并且是form表单提交类型，否则为失败
            if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST")
               || !httpContext.Request.HasFormContentType))
            {
                context.Fail();
                return;
            }
            context.Succeed(requirement);

        }

    }
}
